#include "videoio_client.h"

video_property video_probs;
/*---------------------------------------------------------
	传视频客户端
	video_name: 视频路径
	cpuid:		绑定到某核
	sock_tcp:   客户端套接字
----------------------------------------------------------*/
void videoTransClient(const char *video_name, int cpuid, int sock_tcp[]) 
{
	// int initialization_finished = 1;
	cpu_set_t mask;

	CPU_ZERO(&mask);
	CPU_SET(cpuid, &mask);

	if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0)
		cerr << "set thread affinity failed" << endl;

	printf("Bind videoTransClient process to CPU %d\n", cpuid); 

	cv::VideoCapture video;
	if (!video.open(video_name)) {
		cout << "Fail to open " << video_name << endl;
		return;
	}

	video_probs.Frame_cnt = video.get(CV_CAP_PROP_FRAME_COUNT);
    video_probs.Fps = video.get(CV_CAP_PROP_FPS);
    video_probs.Video_width = video.get(CV_CAP_PROP_FRAME_WIDTH);
    video_probs.Video_height = video.get(CV_CAP_PROP_FRAME_HEIGHT);
    video_probs.Video_fourcc = video.get(CV_CAP_PROP_FOURCC);
	for(int i=0;i<SOCKETNUM;i++){
		send(sock_tcp[i], &video_probs, sizeof(video_probs), 0);
	}

	bReading = true;//读写状态标记
	while (1) 
	{  
		if (queueInput_client.size() >= 300){
			sleep(1);
			continue;
		}
		cv::Mat img, img_gray;
		// 如果读不到图片 或者 bReading 不在读取状态则跳出
		if (!bReading || !video.read(img) || idxInputImage >= video_probs.Frame_cnt) {
			// cout << "read video stream failed! Maybe to the end!" << endl;
			// video.set(CV_CAP_PROP_POS_FRAMES, 0);
			// continue;
			video.release();
			break;
		}
		mtxQueueInput_client.lock();
		queueInput_client.push(make_pair(idxInputImage, img));
		mtxQueueInput_client.unlock();
		
		vector<uchar> data_encode;
		std::vector<int> quality;
		quality.push_back(CV_IMWRITE_JPEG_QUALITY);
		quality.push_back(50);//进行50%的压缩
		cvtColor(img, img_gray,cv::COLOR_RGB2GRAY);
		imencode(".jpg", img_gray, data_encode, quality);

		char encodeImg[65535];
		int nSize = data_encode.size();
		int idx = (idxInputImage / BATCHSIZE) % 2;
		send(sock_tcp[idx], &idxInputImage, sizeof(int), 0);
		send(sock_tcp[idx], &nSize, sizeof(int), 0);
		for (int i = 0; i < nSize; i++)
		{
			encodeImg[i] = data_encode[i];
		}
		send(sock_tcp[idx], encodeImg, nSize, 0);
		idxInputImage++;
	}
	bReading = false;
	for(int i=0;i<SOCKETNUM;i++){
		shutdown(sock_tcp[i], SHUT_WR);
	}
	cout << "VideoRead is over." << endl;
}

/*---------------------------------------------------------
	写视频
----------------------------------------------------------*/
void videoWrite(int cpuid) 
{
	cpu_set_t mask;
	CPU_ZERO(&mask);
	CPU_SET(cpuid, &mask);

	if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0)
		cerr << "set thread affinity failed" << endl;

	printf("Bind VideoCapture process to CPU %d\n", cpuid); 

	cv::VideoWriter vid_writer;
    while(1)
    {
       if(queueInput_client.size() > 0)
       {
            // cout << video_probs.Video_width << " " << video_probs.Video_height << endl;
            vid_writer  = cv::VideoWriter(SAVE_PATH, video_probs.Video_fourcc, video_probs.Fps, 
										  cv::Size(video_probs.Video_width, video_probs.Video_height));
            break;
       }
    }

	while (1) 
	{  
		usleep(10);
		cv::Mat img;

		// 如果queueOutput存在元素 就一直写
		if (queueOutput.size() > 0) {
			mtxQueueOutput.lock();
			img = queueOutput.front();
			queueOutput.pop();
			mtxQueueOutput.unlock();

			vid_writer.write(img); // Save-video
		}
		// 最后一帧检测结束 bWriting置为false 此时如果queueOutput仍存在元素 继续写
		else if(!bDetecting){
			vid_writer.release();
			break;
		}
	}
	cout << "VideoWrite is over." << endl;
}
